package org.apache.servicecomb.samples.practise.houserush.gateway.filter;

import com.netflix.config.DynamicPropertyFactory;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor;
import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.OperationMeta;
import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
import org.apache.servicecomb.swagger.invocation.Response;
import org.apache.servicecomb.swagger.invocation.context.HttpStatus;
import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
import org.apache.servicecomb.swagger.invocation.response.ResponseMeta;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultHttpClientFilter implements HttpClientFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHttpClientFilter.class);
    private static final boolean enabled = DynamicPropertyFactory.getInstance().getBooleanProperty("servicecomb.http.filter.client.default.enabled", true).get();

    public DefaultHttpClientFilter() {
    }

    public int getOrder() {
        return 2147483647;
    }

    public boolean enabled() {
        return enabled;
    }

    public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) {
    }

    protected ProduceProcessor findProduceProcessor(RestOperationMeta restOperation, HttpServletResponseEx responseEx) {
        String contentType = responseEx.getHeader("Content-Type");
        if (contentType == null) {
            return null;
        } else {
            String contentTypeForFind = contentType;
            int idx = contentType.indexOf(59);
            if (idx != -1) {
                contentTypeForFind = contentType.substring(0, idx);
            }

            return restOperation.findProduceProcessor(contentTypeForFind);
        }
    }

    protected Response extractResponse(Invocation invocation, HttpServletResponseEx responseEx) {
        Object result = invocation.getHandlerContext().get("servicecomb-readStreamPart");
        if (result != null) {
            return Response.create(responseEx.getStatusType(), result);
        } else {
            OperationMeta operationMeta = invocation.getOperationMeta();
            ResponseMeta responseMeta = operationMeta.findResponseMeta(responseEx.getStatus());
            RestOperationMeta swaggerRestOperation = (RestOperationMeta)operationMeta.getExtData("swaggerRestOperation");
            ProduceProcessor produceProcessor = this.findProduceProcessor(swaggerRestOperation, responseEx);
            if (produceProcessor == null) {
                String msg = String.format("method %s, path %s, statusCode %d, reasonPhrase %s, response content-type %s is not supported", swaggerRestOperation.getHttpMethod(), swaggerRestOperation.getAbsolutePath(), responseEx.getStatus(), responseEx.getStatusType().getReasonPhrase(), responseEx.getHeader("Content-Type"));
                LOGGER.warn(msg);
                produceProcessor = ProduceProcessorManager.DEFAULT_PROCESSOR;
            }

            try {
                result = produceProcessor.decodeResponse(responseEx.getBodyBuffer(), responseMeta.getJavaType());
                return Response.create(responseEx.getStatusType(), result);
            } catch (Exception var10) {
                LOGGER.error("failed to decode response body, exception is [{}]", var10.getMessage());
                String msg = String.format("method %s, path %s, statusCode %d, reasonPhrase %s, response content-type %s is not supported", swaggerRestOperation.getHttpMethod(), swaggerRestOperation.getAbsolutePath(), responseEx.getStatus(), responseEx.getStatusType().getReasonPhrase(), responseEx.getHeader("Content-Type"));
                return HttpStatus.isSuccess(responseEx.getStatus()) ? Response.createConsumerFail(new InvocationException(400, responseEx.getStatusType().getReasonPhrase(), new CommonExceptionData(msg), var10)) : Response.createConsumerFail(new InvocationException(responseEx.getStatus(), responseEx.getStatusType().getReasonPhrase(), new CommonExceptionData(msg), var10));
            }
        }
    }

    public Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx) {
        Response response = this.extractResponse(invocation, responseEx);
        Iterator var4 = responseEx.getHeaderNames().iterator();

        while(true) {
            String headerName;
            do {
                if (!var4.hasNext()) {

                    //在返回响应之前，需要进行token的设置
                    //获取续签后的token
                    String newAuthorization = invocation.getContext("newAuthorization");
                    //如果续签后的token不为空，就是获取到了，设置到响应头中
                    if (newAuthorization != null){
                        response.getHeaders().addHeader("newAuthorization",newAuthorization);
                    }
                    return response;
                }

                headerName = (String)var4.next();
            } while(headerName.equals(":status"));

            Collection<String> headerValues = responseEx.getHeaders(headerName);
            Iterator var7 = headerValues.iterator();

            while(var7.hasNext()) {
                String headerValue = (String)var7.next();
                response.getHeaders().addHeader(headerName, headerValue);
            }
        }
    }

}